Regular Surfaces: Graphs

Let $f: D \subseteq \mathbb{R}^2 \to \mathbb{R}$ be a smooth function where $D$ is an open set. The graph of $f$ over $D$ is the subset $$ \operatorname{graph}(f) = \{(x, y, f(x, y)) : (x, y) \in D\} \subseteq \mathbb{R}^3. $$ It is the set of points $z = f(x, y)$.

x = np.linspace(0, 1, 10)
y = np.linspace(0, 1, 10)
X, Y = np.meshgrid(x, y)

def f(x, y):
    return (x-0.5)**2 + (y-0.5)**2

Z = f(X, Y)
fig = go.Figure(data = go.Surface(x=x, y=y, z=Z))
fig.update_layout(title = r"$z = (x-\tfrac{1}{2})^2 + (y-\tfrac{1}{2})^2$", scene_camera = camera)
fig.show()

Parametrisation

A parametrisation for a graph is the map $$ \varphi(u, v) = (u, v, f(u, v)). $$ Thus $\operatorname{graph}(f) = \varphi(D) := \{\varphi(u, v) : (u, v) \in D\}$. Here we distunguish between the parametrisation variables $(u, v)$ (the independent variables) and the set variables $(x, y, z)$ (the dependent variables). This distinction can be useful to avoid confusion at times (as we'll see below), and is useful for later generalisations. For now, just note that we have $x = u, y = v, z = f(u, v)$. That is, each component $(x,y,z)$ is a function of the parameters $(u, v)$ with $x$ and $y$ simply just $u$ and $v$ respectively.

u = np.linspace(0, 1, 10)
v = np.linspace(0, 1, 10)

U, V = np.meshgrid(u, v)

def phi(u, v):
    return (u, v, (u-0.5)**2 + (v-0.5)**2)
    
p = phi(U, V)
fig = go.Figure(data = go.Surface(x=p[0], y=p[1], z=p[2]))
fig.update_layout(title = r"$(x, y, z) = \varphi(u,v) = \big(u, v, (u-\tfrac{1}{2})^2 + (v-\tfrac{1}{2})^2\big)$", scene_camera = camera)
fig.show()

Hemisphere

Let $$ f(x, y) = \sqrt{1 - x^2 + y^2}, \quad x^2 + y^2 < 1. $$ Then $\operatorname{graph}(f)$ is the upper hemisphere minus the equator $E = \{x^2 + y^2 = 1, z = 0\}$.

We now encouter an issue when trying to plot the hemisphere. The plots above used rectangular domains created with meshgrid from numpy. Now our domain is the unit disc $\{(x, y) : x^2 + y^2 < 1\}$. We can resolve the issue by using polar coordinates: $$ x = r \cos\theta, \quad y = r\sin\theta $$ with $(r, \theta)$ in a rectangle, $$ 0 < r <1, \quad 0 < \theta < 2\pi. $$ Then we use a two-stage process to create our $(x,y)$-arrays for plotting:

  1. Generate the $(r, \theta)$ mesh as a rectangular mesh.
  2. Generate $(x, y)$ arrays from the rectangular mesh. Then we can generatete $z$ array as $z = f(x, y)$ as before.
# Build our unit circle mesh

eps = 0.001 # We need to avoid rounding errors for numbers close to 0 creating negatives under square roots

r = np.linspace(0, 1-eps, 20)
th = np.linspace(0, 2*np.pi, 20)

R, Th = np.meshgrid(r, th)

X = R*np.cos(Th)
Y = R*np.sin(Th)

# Plot the (x, y) meshgrid
fig = px.scatter(x = X.ravel(), y = Y.ravel())
fig.update_layout(width = 500, height = 500, title = "Polar grid")
fig.show()
def f(x, y):
    return np.sqrt(1.0 - x**2 - y**2)

Z = f(X, Y)

fig = go.Figure(data = go.Surface(x=X, y=Y, z=Z))
fig.update_layout(title = r"$z = \sqrt{1-x^2-y^2}$", scene_camera = camera)
fig.show()

Non graph parametrisation of hemisphere

Now is a good time to point out that non-graphical parametrisations can be quite useful. For this, we consider $f$ as a function of $(r, \theta)$ instead of $(x, y)$ by composition: $$ f(r, \theta) = \sqrt{1 - r^2 \cos^2\theta - r^2 \sin^2\theta} = \sqrt{1-r^2} $$ where we may a common abuse of notation and write still call the function $f$. Now the hemisphere is given by $$ \{(r\cos\theta, r\sin\theta, \sqrt{1-r^2}): 0 < r < 1, 0 < \theta < 2*\pi\}. $$ That is we may define the parametrisation $$ \varphi(r, \theta) = (r\cos\theta, r\sin\theta, \sqrt{1-r^2}) $$ for $(r, \theta) \in (0, 1) \times (0, 2\pi)$.

Thus we may work directly with $(r, \theta)$ gaining the advantage of a rectangular grid, but we no longer have a graph of a function. Note here that $(r, \theta)$ are playing the role of $(u, v)$ above as it's traditional to use $(r, \theta)$ for polar coordinates. We could just as easily have written $$ \varphi(u, v) = (u\cos v, u\sin v, \sqrt{1-v^2}) $$ for $(u, v) \in (0, 1) \times (0, 2\pi)$. Observe in particulaa that $x \ne u$ and $y \ne v$ in contrast to the parametrisation of a graph.

eps = 0.001 # We need to avoid rounding errors for numbers close to 0 creating negatives under square roots

r = np.linspace(0, 1-eps, 20)
th = np.linspace(0, 2*np.pi, 20)

R, Th = np.meshgrid(r, th)

def phi(r, th):
    return (r*np.cos(th), r*np.sin(th), np.sqrt(1-r**2))
    
p = phi(R, Th)
fig = go.Figure(data = go.Surface(x=p[0], y=p[1], z=p[2]))
fig.update_layout(title = r"$(x, y, z) = \varphi(r, \theta) = \big(r \cos\theta, r \sin\theta, \sqrt{1-r^2} \big)$", scene_camera = camera)
fig.show()

For now, it was just worthwhile pointing out how a non-graphical parametrisation arises quite naturally and we'll focus our attention on graphs, returning to more general parametrisations another time.

Saddle surface

Let $f(x, y) = x^2 - y^2$. The graph of $f$ looks like a saddle. At every point, in one direction the surface bends downwards and bends upward in the perpendicular direction.

x = np.linspace(-1, 1,20)
y = np.linspace(-1, 1, 20)
X, Y = np.meshgrid(x, y)

def f(x, y):
    return x**2 - y**2

Z = f(X, Y)
fig = go.Figure(data = go.Surface(x=x, y=y, z=Z))
fig.update_layout(title = r"$z = x^2 - y^2$", scene_camera = camera)
fig.show()

Part of a Helicoid

A Helicoid is the surface $$ x = r \cos\theta, \quad y = r \sin\theta, \quad z = \theta. $$

Restricting to range $0 < \theta < 2\pi$ it can be written as a graph $$ z = \arctan_2(y, x) $$ where $\arctan_2$ computes the angle $\theta$ between positive $x$-axis and the ray through the origin and the point $(x, y)$ in the plane. This accounts for the correct quadrant - in the positive quadrant $\arctan_2(y, x) = \arctan(y/x)$. See https://en.wikipedia.org/wiki/Atan2 for details.

We'll plot it on a rectangular grid for convenience, but it does make it look a little odd.

x = np.linspace(-2, 2, 30)
y = np.linspace(-2, 2, 30)
X, Y = np.meshgrid(x, y)

def f(x, y):
    return np.arctan2(y, x)

Z = f(X, Y)
fig = go.Figure(data = go.Surface(x=x, y=y, z=Z))
fig.update_layout(title = r"$z = \arctan_2(y, x)$", scene_camera = camera)
fig.show()

Note that it would be simpler to parametrise the Helicoid using $(r,\theta)$ above, again showing that in some cases graphs are more naturally parametrised in a non-graphical way, and moreover that some surfaces cannot be fully described in a non-graphical way. Below is a plot of a few "turns" of the Helicoid showing it's not a graph over the $(x,y)$ plane since there are multiple points $(x,y,z)$ on the Helicoid over the each point $(x,y)$ in the plane.

r = np.linspace(0, 5, 30)
th = np.linspace(0, 6*np.pi, 80)

R, Th = np.meshgrid(r, th)

def phi(r, th):
    return (r*np.cos(th), r*np.sin(th), th)
    
p = phi(R, Th)
fig = go.Figure(data = go.Surface(x=p[0], y=p[1], z=p[2]))
fig.update_layout(title = r"$(x, y, z) = \varphi(r, \theta) = \big(r \cos\theta, r \sin\theta, \theta\big)$", scene_camera = camera)
fig.show()